ubus: implement UBus method to get state data immediately
authorNicolas BESNARD <[email protected]>
Tue, 19 Nov 2024 12:46:22 +0000 (12:46 +0000)
committerÁlvaro Fernández Rojas <[email protected]>
Mon, 3 Nov 2025 15:21:24 +0000 (16:21 +0100)
Problem:
    odhcp6c state data are transmitted when the DHCPv6 state changes.
    If a process subscribes after the start of odhcp6c, then it has to
    wait for the next update event.

Solution:
    Add a new UBus method "get_state" to get the latest state data
    immediately.

Signed-off-by: Nicolas BESNARD <[email protected]>
Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcp6c/pull/106
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
src/dhcpv6.c
src/odhcp6c.h
src/ubus.c

index 9d4081a55d087a35840f7446f8b3492bf1a10961..9637adae1f96503a279ff4f3c1bf2a07792f365a 100644 (file)
@@ -209,6 +209,83 @@ static char *dhcpv6_status_code_to_str(uint16_t code)
        return "Unknown";
 }
 
+const char *dhcpv6_state_to_str(enum dhcpv6_state state)
+{
+       switch (state) {
+       case DHCPV6_INIT:
+               return "INIT";
+
+       case DHCPV6_SOLICIT:
+               return "SOLICIT";
+
+       case DHCPV6_SOLICIT_PROCESSING:
+               return "SOLICIT_PROCESSING";
+
+       case DHCPV6_ADVERT:
+               return "ADVERT";
+
+       case DHCPV6_REQUEST:
+               return "REQUEST";
+
+       case DHCPV6_REQUEST_PROCESSING:
+               return "REQUEST_PROCESSING";
+
+       case DHCPV6_REPLY:
+               return "REPLY";
+
+       case DHCPV6_BOUND:
+               return "BOUND";
+
+       case DHCPV6_BOUND_PROCESSING:
+               return "BOUND_PROCESSING";
+
+       case DHCPV6_BOUND_REPLY:
+               return "BOUND_REPLY";
+
+       case DHCPV6_RECONF:
+               return "RECONF";
+
+       case DHCPV6_RECONF_PROCESSING:
+               return "RECONF_PROCESSING";
+
+       case DHCPV6_RECONF_REPLY:
+               return "RECONF_REPLY";
+
+       case DHCPV6_RENEW:
+               return "RENEW";
+
+       case DHCPV6_RENEW_PROCESSING:
+               return "RENEW_PROCESSING";
+
+       case DHCPV6_RENEW_REPLY:
+               return "RENEW_REPLY";
+
+       case DHCPV6_REBIND:
+               return "REBIND";
+
+       case DHCPV6_REBIND_PROCESSING:
+               return "REBIND_PROCESSING";
+
+       case DHCPV6_REBIND_REPLY:
+               return "REBIND_REPLY";
+
+       case DHCPV6_INFO:
+               return "INFO";
+
+       case DHCPV6_INFO_PROCESSING:
+               return "INFO_PROCESSING";
+
+       case DHCPV6_INFO_REPLY:
+               return "INFO_REPLY";
+
+       case DHCPV6_EXIT:
+               return "EXIT";
+
+       default:
+               return "INVALID_STATE";
+       }
+}
+
 static int fd_set_nonblocking(int sockfd)
 {
        int flags = fcntl(sockfd, F_GETFL, 0);
index 0f1692a2bcd9b1d6a6d88425c1208324cc3006b3..a28decc8aa90cf566fd2375e0cc296c0e04ef273 100644 (file)
@@ -441,6 +441,7 @@ int dhcpv6_state_processing(enum dhcpv6_msg type);
 int dhcpv6_get_state_timeout(void);
 void dhcpv6_set_state_timeout(int timeout);
 void dhcpv6_reset_state_timeout(void);
+const char *dhcpv6_state_to_str(enum dhcpv6_state state);
 
 int init_rtnetlink(void);
 int set_rtnetlink_addr(int ifindex, const struct in6_addr *addr,
index c369e7d8671bf50819246423f31bde67b7ec8791..ebe16ae5cfc086ed0887a9caa6f0b106f989cdd4 100644 (file)
@@ -104,10 +104,13 @@ static char ubus_name[24];
 static int ubus_handle_get_state(struct ubus_context *ctx, struct ubus_object *obj,
                struct ubus_request_data *req, const char *method, struct blob_attr *msg);
 
-static struct ubus_object_type odhcp6c_object_type = {
-       .name = "odhcp6c"
+static struct ubus_method odhcp6c_object_methods[] = {
+       UBUS_METHOD_NOARG("get_state", ubus_handle_get_state),
 };
 
+static struct ubus_object_type odhcp6c_object_type = 
+       UBUS_OBJECT_TYPE("odhcp6c", odhcp6c_object_methods);
+
 static struct ubus_object odhcp6c_object = {
        .name = NULL,
        .type = &odhcp6c_object_type,
@@ -452,13 +455,9 @@ static int s46_to_blob(enum odhcp6c_state state, const uint8_t *data, size_t len
        return UBUS_STATUS_OK;
 }
 
-int ubus_dhcp_event(const char* status)
+static int states_to_blob(void)
 {
-       if (!ubus || !odhcp6c_object.has_subscribers)
-               return UBUS_STATUS_UNKNOWN_ERROR;
-
        char *buf = NULL;
-
        size_t dns_len, search_len, custom_len, sntp_ip_len, ntp_ip_len, ntp_dns_len;
        size_t sip_ip_len, sip_fqdn_len, aftr_name_len, cer_len, addr_len;
        size_t s46_mapt_len, s46_mape_len, s46_lw_len, passthru_len;
@@ -489,6 +488,8 @@ int ubus_dhcp_event(const char* status)
 
        blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
 
+       blobmsg_add_string(&b, "DHCPV6_STATE", dhcpv6_state_to_str(dhcpv6_get_state()));
+
        CHECK(ipv6_to_blob("SERVER", addr, addr_len / sizeof(*addr)));
        CHECK(ipv6_to_blob("RDNSS", dns, dns_len / sizeof(*dns)));
        CHECK(ipv6_to_blob("SNTP_IP", sntp, sntp_ip_len / sizeof(*sntp)));
@@ -523,6 +524,27 @@ int ubus_dhcp_event(const char* status)
        CHECK_ALLOC(buf);
        script_hexlify(buf, passthru, passthru_len);
        blobmsg_add_string_buffer(&b);
+
+       return UBUS_STATUS_OK;
+}
+
+static int ubus_handle_get_state(struct ubus_context *ctx, _unused struct ubus_object *obj,
+               struct ubus_request_data *req, _unused const char *method,
+               _unused struct blob_attr *msg)
+{
+       CHECK(states_to_blob());
+       CHECK(ubus_send_reply(ctx, req, b.head));
+       blob_buf_free(&b);
+
+       return UBUS_STATUS_OK;
+}
+
+int ubus_dhcp_event(const char *status)
+{
+       if (!ubus || !odhcp6c_object.has_subscribers)
+               return UBUS_STATUS_UNKNOWN_ERROR;
+
+       CHECK(states_to_blob());
        CHECK(ubus_notify(ubus, &odhcp6c_object, status, b.head, -1));
        blob_buf_free(&b);